﻿using HandyControl.Controls;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using QModels;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QServices.Services;

public class AgvCarService : QMainService
{
	public AgvCar GetAgvCarById(string id)
	{
		if (string.IsNullOrWhiteSpace(id)) return default;
		var db = CreateDbContext();
		var info = db.Set<AgvCar>().FirstOrDefault(x => x.ID == id);
		return info;
	}

	public AgvCar? GetAgvCarByNumber(int carNumber)
	{
		var db = CreateDbContext();
		var info = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == carNumber.ToString());
		return info;
	}
	public AgvCar? GetAgvCarByNumber(string carNumber)
	{
		var db = CreateDbContext();
		var info = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == carNumber);



		return info;
	}

	public AgvCar? GetAgvCarByRegion(string region)
	{
		var db = CreateDbContext();
		var info = db.Set<AgvCar>().FirstOrDefault(x => x.Region == region);
		return info;
	}
	public List<AgvCar> GetAgvCarList()
	{
		var db = CreateDbContext();
		var res = db.Set<AgvCar>().OrderBy(x => x.CarNumber).ToList();
		return res;
	}

	public void UpdateAGVElEQty(AgvCar agvCar)
	{
		try
		{
			var db = CreateDbContext();
			var info = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == agvCar.CarNumber);
			if (info != null)
			{
				info.Electricity = agvCar.Electricity;
				info.CarStatus = agvCar.CarStatus;
				db.SaveChanges();
			}
		}
		catch (Exception ex)
		{
			AppRuntime.Logger_Error(ex);
		}


	}

	public bool AddOrUpdateAgvCar(AgvCar info)
	{

		if (info == null) return false;
		var db = CreateDbContext();
		if (string.IsNullOrWhiteSpace(info.ID))
		{

			info.ID = Guid.NewGuid().ToString();
			db.Set<AgvCar>().Add(info);

		}
		else
		{
			var exits = db.Set<AgvCar>().Find(info.ID);
			if (exits != null)
			{
				exits.CarNumber = info.CarNumber;
				exits.Description = info.Description;
			}

		}

		db.SaveChanges();
		return true;
	}

	public bool UpdateAgvCarPLC(AgvCar info)
	{
		if (info == null) return false;
		var db = CreateDbContext();
		var exits = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == info.CarNumber);
		if (exits != null)
		{
			exits.PlcType = info.PlcType;
			exits.IP = info.IP;
		}
		db.SaveChanges();
		return true;
	}
	public bool DeleteAgvCar(string id)
	{
		var db = CreateDbContext();
		var info = db.Set<AgvCar>().FirstOrDefault(y => y.ID == id);
		if (info != null)
		{
			db.Set<AgvCar>().Remove(info);

		}

		db.SaveChanges();
		return true;
	}

	public bool UpdateCarInfo(string carNumber, CarStatus carStatus, decimal electricity)
	{
		var db = CreateDbContext();
		var info = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == carNumber);
		if (info != null)
		{
			info.CarStatus = carStatus;
			info.Electricity = electricity;
		}
		db.SaveChanges();
		return true;
	}

	public bool UpdateCarPlcOtherSetting(string carNumber, string ip, decimal? maxElectricQty, decimal? minAllowEleQty)
	{
		var db = CreateDbContext();
		var info = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == carNumber);
		if (info == null) return false;
		if (info != null)
		{
			info.IP = ip;
			info.MaxElectricQty = maxElectricQty;
			info.MinAllowEleQty = minAllowEleQty;

		}
		db.SaveChanges();

		return true;
	}

	public bool UpdateCarInfoAndSchedule(AgvCar info, DosingSchedule schedule)
	{
		using var db = CreateDbContext();
		var car = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == info.CarNumber);
		if (car == null) return false;
		var exit_schedule = db.Set<DosingSchedule>().FirstOrDefault(x => x.CarId == car.ID);
		if (exit_schedule == null) return false;

		car.IP = info.IP;
		car.MaxElectricQty = info.MaxElectricQty;
		car.MinAllowEleQty = info.MinAllowEleQty;

		exit_schedule.First_80 = schedule.First_80;
		exit_schedule.First_120 = schedule.First_120;
		exit_schedule.First_160 = schedule.First_160;
		exit_schedule.First_200 = schedule.First_200;

		exit_schedule.Second_80 = schedule.Second_80;
		exit_schedule.Second_120 = schedule.Second_120;
		exit_schedule.Second_160 = schedule.Second_160;
		exit_schedule.Second_200 = schedule.Second_200;

		exit_schedule.Third_80 = schedule.Third_80;
		exit_schedule.Third_120 = schedule.Third_120;
		exit_schedule.Third_160 = schedule.Third_160;
		exit_schedule.Third_200 = schedule.Third_200;

		exit_schedule.HourFirst = schedule.HourFirst;
		exit_schedule.HourSecond = schedule.HourSecond;
		exit_schedule.HourThird = schedule.HourThird;

		exit_schedule.MinuteFirst = schedule.MinuteFirst;
		exit_schedule.MinuteSecond = schedule.MinuteSecond;
		exit_schedule.MinuteThird = schedule.MinuteThird;




		db.SaveChanges();
		return true;

	}


	public void SaveLocalData3Server()
	{

		try
		{
			var db = new SqliteDbContext();
			var lst = db.Set<AGVCarStatusModel>().Where(x => x.IsCopy == false && !string.IsNullOrWhiteSpace(x.BarCode)).Take(1000).ToList();
			lst.ForEach(x => x.IsCopy = true);
			var remotedb = CreateDbContext();
			remotedb.AddRange(lst);
			remotedb.SaveChanges();
			db.SaveChanges();
		}
		catch (Exception ex)
		{
			AppRuntime.Logger_Error(ex);
			SqliteDBHelper.InitDB_Table();
		}


	}

	public void  GetAgvCarAndDosingScheduleFromRemote()
	{
		if (!AppRuntime.IsNetworkAvailable()) return;
		try
		{
			using var db = CreateSqlserverDbContext();
			using var mysqldb = CreateMySqlDbContext();
			var car = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == AppRuntime.CarNumber);
			var schedule = db.Set<DosingSchedule>().FirstOrDefault(x => x.CarId == car.ID);
			var cages = db.Set<PigeonCage>().ToList();
			mysqldb.Set<AgvCar>().Update(car);
			mysqldb.Set<DosingSchedule>().Update(schedule);
			mysqldb.UpdateRange(cages);
			mysqldb.SaveChanges();
		}
		catch(Exception ex)
		{
			AppRuntime.Logger_Error(ex);
		}
		

	}
	public async Task ChangeMqttCacheFromRemote()
	{
		if (!AppRuntime.IsNetworkAvailable()) return;

		try
		{
			using var db = CreateSqlserverDbContext();
			using var mysqldb = CreateMySqlDbContext();
			var mqttcache = db.Set<MqttCache>().Where(x => x.CarNumber == AppRuntime.CarNumber && x.IsClose == 0).ToList();
			if (mqttcache.Count <= 0) return;
			if (mqttcache != null && mqttcache.Count > 0)
			{

				var car = db.Set<AgvCar>().FirstOrDefault(x => x.CarNumber == AppRuntime.CarNumber);
				
				var schedule = db.Set<DosingSchedule>().FirstOrDefault(x => x.CarId == car.ID);
				
				mqttcache.ForEach(x =>
				{
					x.IsClose = 1;
					x.LastUpdateTime = DateTime.Now;
				});
				if (mqttcache.Any(x => x.EventType == MqttCacheEventType.UpdateCarStatus||x.EventType==MqttCacheEventType.UpdateDosingSchedule))
				{
					if (car != null) mysqldb.Set<AgvCar>().Update(car);
					if (schedule != null) mysqldb.Set<DosingSchedule>().Update(schedule);

					AppRuntime.IsUpdateUpdateCarStatus = true;
				}
				
				if (mqttcache.Any(x => x.EventType == MqttCacheEventType.UpdateCarElectricLimit))
				{
					if (car != null)
					{
						AppRuntime.GetPlcManager().UpdateCarMaxMinElectricQty((int)car.MinAllowEleQty, (int)car.MaxElectricQty);
						AppRuntime.AgvCar = car;

					}
				}
				if (mqttcache.Any(x => x.EventType == MqttCacheEventType.UpdateChongDianTask))
				{
					var t_schedule = await AppRuntime.SchedulerFactory.GetScheduler();
					var trigger = await t_schedule.GetTrigger(new TriggerKey("CarElectricJobTrigger", "AGV"));
					if (trigger != null)
					{

						if (car != null)
						{
							if (AppRuntime.IsDebug)
							{
								var tt = DateTime.Now.AddMinutes(1);
								var hour = tt.Hour;
								var minute = tt.Minute;
								var newtrigger = trigger.GetTriggerBuilder().WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(hour, minute)).Build();
								await t_schedule.RescheduleJob(trigger.Key, newtrigger);
							}
							else
							{
								var newtrigger = trigger.GetTriggerBuilder().WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(car.TaskHour, car.TaskMinute)).Build();
								await t_schedule.RescheduleJob(trigger.Key, newtrigger);

							}

							if (!t_schedule.IsStarted)
							{
								await t_schedule.Start();
							}
						}

					}

				}
				if (mqttcache.Any(x => x.EventType == MqttCacheEventType.UpdatePigeonCage))
				{
					var cages = db.Set<PigeonCage>().ToList();
					mysqldb.UpdateRange(cages);
					AppRuntime.IsUpdatePigeonCage = true;

				}
				
			}


			mysqldb.SaveChanges();
			db.SaveChanges();
		}
		catch (Exception ex)
		{
			AppRuntime.Logger_Error(ex);
		}
		
	
	
	
	}


	public (List<AGVCarStatusModel> First, List<AGVCarStatusModel> Second, List<AGVCarStatusModel> Third) GetTodayAgvErrorData()
	{
		var today = DateTime.Now.ToString("yyyy-MM-dd");
		using var db = CreateDbContext();
		var lst = db.Set<AGVCarStatusModel>().ToList().Where(x => !string.IsNullOrWhiteSpace(x.CreateTime)
		&& x.CreateTime.Contains(today)
		&& !string.IsNullOrWhiteSpace(x.BarCode)).ToList();
		var dic_1 = new Dictionary<string, AGVCarStatusModel>();
		var dic_2 = new Dictionary<string, AGVCarStatusModel>();
		var dic_3 = new Dictionary<string, AGVCarStatusModel>();
		for (int i = 0; i < lst.Count; i++)
		{
			if (lst[i].FeedNumber == 1)
			{
				if (dic_1.ContainsKey(lst[i].BarCode))
				{
					if (string.Compare(dic_1[lst[i].BarCode].CreateTime, lst[i].CreateTime) < 0)
					{
						dic_1[lst[i].BarCode] = lst[i];
					}
				}
				else
				{

					dic_1.Add(lst[i].BarCode, lst[i]);
				}
			}
			else if (lst[i].FeedNumber == 2)
			{
				if (dic_2.ContainsKey(lst[i].BarCode))
				{
					if (string.Compare(dic_2[lst[i].BarCode].CreateTime, lst[i].CreateTime) < 0)
					{
						dic_2[lst[i].BarCode] = lst[i];
					}
				}
				else
				{

					dic_2.Add(lst[i].BarCode, lst[i]);
				}
			}
			else if (lst[i].FeedNumber == 3)
			{

				if (dic_3.ContainsKey(lst[i].BarCode))
				{
					if (string.Compare(dic_3[lst[i].BarCode].CreateTime, lst[i].CreateTime) < 0)
					{
						dic_3[lst[i].BarCode] = lst[i];
					}
				}
				else
				{

					dic_3.Add(lst[i].BarCode, lst[i]);
				}

			}

		}



		return (dic_1.Values.ToList(), dic_2.Values.ToList(), dic_3.Values.ToList());

	}



	public void UpdateAGVCarStatusModelToRemote()
	{
		if (AppRuntime.IsNetworkAvailable())
		{
			try
			{
				using var db = CreateMySqlDbContext();
				var exits = db.Set<AGVCarStatusModel>().Where(x => x.IsCopy == false).Take(1000).ToList();
				exits.ForEach(x => x.IsCopy = true);
				using var sqlserver = CreateSqlserverDbContext();
				sqlserver.Set<AGVCarStatusModel>().AddRange(exits);
				sqlserver.SaveChanges();
				db.SaveChanges();
			}
			catch (Exception ex)
			{
				AppRuntime.Logger_Error(ex);
			}

		}


	}

	public void AddAGVCarStatusModel2DB(AGVCarStatusModel model)
	{
		using var db=CreateMySqlDbContext();
		db.Set<AGVCarStatusModel>().Add(model);
		db.SaveChanges();
	}

	public void DeleteAGVCarStatusModelLocal()
	{
		using var db = CreateMySqlDbContext();
		var lastdate = DateTime.Now.AddDays(-5).ToString("yyyy-MM-dd HH:mm:ss");
		var sql = $"DELETE  from  agvcarstatusmodel where createtime<'{lastdate}'";
		db.Database.ExecuteSqlRaw(sql);
		db.SaveChanges();
		
	}



}
